package org.fle4y.app.server.database;

import java.sql.SQLException;

/**
 * author : xiehui<br>
 * company : northking <br>
 * Create at: 2012-6-26<br>
 * @version : 1.0<br>
 * mailto:flexie@foxmail.com<br>
 *  Description : 约束
 */
public class Constraint {

	final static int FOREIGN_KEY = 0, MAIN = 1, UNIQUE = 2;
	private int type;
	private int len;;

	private Table tMain;
	private int iColMain[];
	private Index iMain;
	private Object oMain[];

	private Table tRef;
	private int iColRef[];
	private Index iRef;
	private Object oRef[];

	public Constraint(int type, Table t, int col[]) {
		this.type = type;
		tMain = t;
		iColMain = col;
		this.len = col.length;
	}

	public Constraint(int type, Table main, Table ref, int cmain[], int cref[])
			throws SQLException {
		this.type = type;
		tMain = main;
		tRef = ref;
		iColMain = cmain;
		iColRef = cref;
		this.len = cmain.length;

		oMain = tMain.getNewRow();
		oRef = tRef.getNewRow();
		iMain = tMain.getIndexForColumns(cmain);
		iRef = tRef.getIndexForColumns(cref);
	}

	public int getType() {
		return type;
	}

	public Table getMain() {
		return tMain;
	}

	public Table getRef() {
		return tRef;
	}

	public int[] getMainColumns() {
		return iColMain;
	}

	public int[] getRefColumns() {
		return iColRef;
	}

	public void replaceTable(Table old, Table n) throws SQLException {
		if (old == tMain) {
			tMain = n;
		} else if (old == tRef) {
			tRef = n;
		} else {
			throw new SQLException("不能替换 !");
		}
	}

	public void checkInsert(Object row[]) throws SQLException {
		if (type == MAIN || type == UNIQUE) {
			return;
		}

		for (int i = 0; i < len; i++) {
			Object o = row[iColRef[i]];
			if (o == null) {
				return;
			}

			oMain[iColMain[i]] = o;
		}
	}

	public void checkDelete(Object row[]) throws SQLException {
		if (type == FOREIGN_KEY || type == UNIQUE) {
			return;
		}
		for (int i = 0; i < len; i++) {
			Object o = row[iColMain[i]];

			if (o == null) {
				return;
			}

			oRef[iColRef[i]] = o;
		}
	}

	public void checkUpdate(int col[], Result deleted, Result inserted)
			throws SQLException {
		if (type == UNIQUE) {
			return;
		}

		if (type == MAIN) {
			if (!isAffected(col, iColMain, len)) {
				return;
			}
			Record r = deleted.rRoot;

			while (r != null) {
				if (iMain.find(r.data) == null) {
					checkDelete(r.data);
				}

				r = r.next;
			}
		} else if (type == FOREIGN_KEY) {
			if (!isAffected(col, iColMain, len)) {
				return;
			}
			Record r = inserted.rRoot;

			while (r != null) {
				checkInsert(r.data);

				r = r.next;
			}
		}
	}

	private boolean isAffected(int col[], int col2[], int len) {
		if (type == UNIQUE) {
			return false;
		}

		for (int i = 0; i < col.length; i++) {
			int c = col[i];

			for (int j = 0; j < len; j++) {
				if (c == col2[j]) {
					return true;
				}
			}
		}

		return false;
	}

}
